#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int compare(const void* a, const void* b) {
  if (*(int*)a > *(int*)b)
    return 1;
  if (*(int*)a < *(int*)b)
    return -1;
  return 0;
}

struct gameState* newGame() {
  struct gameState* g = malloc(sizeof(struct gameState));
  return g;
}

int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7,
		  int k8, int k9, int k10) {
  int* k = malloc(10 * sizeof(int));
  k[0] = k1;
  k[1] = k2;
  k[2] = k3;
  k[3] = k4;
  k[4] = k5;
  k[5] = k6;
  k[6] = k7;
  k[7] = k8;
  k[8] = k9;
  k[9] = k10;
  return k;
}

int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed,
		   struct gameState *state) {

  int i;
  int j;
  int it;			
  //set up random number generator
  SelectStream(1);
  PutSeed((long)randomSeed);
  
  //check number of players
  if (numPlayers > MAX_PLAYERS || numPlayers < 2)
    {
      return -1;
    }

  //set number of players
  state->numPlayers = numPlayers;

  //check selected kingdom cards are different
  for (i = 0; i < 10; i++)
    {
      for (j = 0; j < 10; j++)
        {
	  if (j != i && kingdomCards[j] == kingdomCards[i])
	    {
	      return -1;
	    }
        }
    }


  //initialize supply
  ///////////////////////////////

  //set number of Curse cards
  if (numPlayers == 2)
    {
      state->supplyCount[curse] = 10;
    }
  else if (numPlayers == 3)
    {
      state->supplyCount[curse] = 20;
    }
  else
    {
      state->supplyCount[curse] = 30;
    }

  //set number of Victory cards
  if (numPlayers == 2)
    {
      state->supplyCount[estate] = 8;
      state->supplyCount[duchy] = 8;
      state->supplyCount[province] = 8;
    }
  else
    {
      state->supplyCount[estate] = 12;
      state->supplyCount[duchy] = 12;
      state->supplyCount[province] = 12;
    }

  //set number of Treasure cards
  state->supplyCount[copper] = 60 - (7 * numPlayers);
  state->supplyCount[silver] = 40;
  state->supplyCount[gold] = 30;

  //set number of Kingdom cards
  for (i = adventurer; i <= treasure_map; i++)       	//loop all cards
    {
      for (j = 0; j < 10; j++)           		//loop chosen cards
	{
	  if (kingdomCards[j] == i)
	    {
	      //check if card is a 'Victory' Kingdom card
	      if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens)
		{
		  if (numPlayers == 2){ 
		    state->supplyCount[i] = 8; 
		  }
		  else{ state->supplyCount[i] = 12; }
		}
	      else
		{
		  state->supplyCount[i] = 10;
		}
	      break;
	    }
	  else    //card is not in the set choosen for the game
	    {
	      state->supplyCount[i] = -1;
	    }
	}

    }

  ////////////////////////
  //supply intilization complete

  //set player decks
  for (i = 0; i < numPlayers; i++)
    {
      state->deckCount[i] = 0;
      for (j = 0; j < 3; j++)
	{
	  state->deck[i][j] = estate;
	  state->deckCount[i]++;
	}
      for (j = 3; j < 10; j++)
	{
	  state->deck[i][j] = copper;
	  state->deckCount[i]++;		
	}
    }

  //shuffle player decks
  for (i = 0; i < numPlayers; i++)
    {
      if ( shuffle(i, state) < 0 )
	{
	  return -1;
	}
    }

  //draw player hands
  for (i = 0; i < numPlayers; i++)
    {  
      //initialize hand size to zero
      state->handCount[i] = 0;
      state->discardCount[i] = 0;
      //draw 5 cards
      // for (j = 0; j < 5; j++)
      //	{
      //	  drawCard(i, state);
      //	}
    }
  
  //set embargo tokens to 0 for all supply piles
  for (i = 0; i <= treasure_map; i++)
    {
      state->embargoTokens[i] = 0;
    }

  //initialize first player's turn
  state->outpostPlayed = 0;
  state->phase = 0;
  state->numActions = 1;
  state->numBuys = 1;
  state->playedCardCount = 0;
  state->whoseTurn = 0;
  state->handCount[state->whoseTurn] = 0;
  //int it; move to top

  //Moved draw cards to here, only drawing at the start of a turn
  for (it = 0; it < 5; it++){
    drawCard(state->whoseTurn, state);
  }

  updateCoins(state->whoseTurn, state, 0);

  return 0;
}

int shuffle(int player, struct gameState *state) {
 

  int newDeck[MAX_DECK];
  int newDeckPos = 0;
  int card;
  int i;

  if (state->deckCount[player] < 1)
    return -1;
  qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare); 
  /* SORT CARDS IN DECK TO ENSURE DETERMINISM! */

  while (state->deckCount[player] > 0) {
    card = floor(Random() * state->deckCount[player]);
    newDeck[newDeckPos] = state->deck[player][card];
    newDeckPos++;
    for (i = card; i < state->deckCount[player]-1; i++) {
      state->deck[player][i] = state->deck[player][i+1];
    }
    state->deckCount[player]--;
  }
  for (i = 0; i < newDeckPos; i++) {
    state->deck[player][i] = newDeck[i];
    state->deckCount[player]++;
  }

  return 0;
}

int playCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state) 
{	
  int card;
  int coin_bonus = 0; 		//tracks coins gain from actions

  //check if it is the right phase
  if (state->phase != 0)
    {
      return -1;
    }
	
  //check if player has enough actions
  if ( state->numActions < 1 )
    {
      return -1;
    }
	
  //get card played
  card = handCard(handPos, state);
	
  //check if selected card is an action
  if ( card < adventurer || card > treasure_map )
    {
      return -1;
    }
	
  //play card
  if ( cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus) < 0 )
    {
      return -1;
    }
	
  //reduce number of actions
  state->numActions--;

  //update coins (Treasure cards may be added with card draws)
  updateCoins(state->whoseTurn, state, coin_bonus);
	
  return 0;
}

int buyCard(int supplyPos, struct gameState *state) {
  int who;
  if (DEBUG){
    printf("Entering buyCard...\n");
  }

  // I don't know what to do about the phase thing.

  who = state->whoseTurn;

  if (state->numBuys < 1){
    if (DEBUG)
      printf("You do not have any buys left\n");
    return -1;
  } else if (supplyCount(supplyPos, state) <1){
    if (DEBUG)
      printf("There are not any of that type of card left\n");
    return -1;
  } else if (state->coins < getCost(supplyPos)){
    if (DEBUG) 
      printf("You do not have enough money to buy that. You have %d coins.\n", state->coins);
    return -1;
  } else {
    state->phase=1;
    //state->supplyCount[supplyPos]--;
    gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard)
  
    state->coins = (state->coins) - (getCost(supplyPos));
    state->numBuys--;
    if (DEBUG)
      printf("You bought card number %d for %d coins. You now have %d buys and %d coins.\n", supplyPos, getCost(supplyPos), state->numBuys, state->coins);
  }

  //state->discard[who][state->discardCount[who]] = supplyPos;
  //state->discardCount[who]++;
    
  return 0;
}

int numHandCards(struct gameState *state) {
  return state->handCount[ whoseTurn(state) ];
}

int handCard(int handPos, struct gameState *state) {
  int currentPlayer = whoseTurn(state);
  return state->hand[currentPlayer][handPos];
}

int supplyCount(int card, struct gameState *state) {
  return state->supplyCount[card];
}

int fullDeckCount(int player, int card, struct gameState *state) {
  int i;
  int count = 0;

  for (i = 0; i < state->deckCount[player]; i++) {
    if (state->deck[player][i] == card) count++;
  }

  for (i = 0; i < state->handCount[player]; i++) {
    if (state->hand[player][i] == card) count++;
  }

  for (i = 0; i < state->discardCount[player]; i++) {
    if (state->discard[player][i] == card) count++;
  }

  return count;
}

int fullDeckCount2(int player, struct gameState *state) {
  return state->deckCount[player] + state->handCount[player] + state->discardCount[player];
}

int whoseTurn(struct gameState *state) {
  return state->whoseTurn;
}

int endTurn(struct gameState *state) {
  int k;
  int i;
  int currentPlayer = whoseTurn(state);
  
  //Discard hand
  for (i = 0; i < state->handCount[currentPlayer]; i++){
    state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard
    state->hand[currentPlayer][i] = -1;//Set card to -1
  }
  state->handCount[currentPlayer] = 0;//Reset hand count
    
  //Code for determining the player
  if (currentPlayer < (state->numPlayers - 1)){ 
    state->whoseTurn = currentPlayer + 1;//Still safe to increment
  }
  else{
    state->whoseTurn = 0;//Max player has been reached, loop back around to player 1
  }

  state->outpostPlayed = 0;
  state->phase = 0;
  state->numActions = 1;
  state->coins = 0;
  state->numBuys = 1;
  state->playedCardCount = 0;
  state->handCount[state->whoseTurn] = 0;

  //int k; move to top
  //Next player draws hand
  for (k = 0; k < 5; k++){
    drawCard(state->whoseTurn, state);//Draw a card
  }

  //Update money
  updateCoins(state->whoseTurn, state , 0);

  return 0;
}

int isGameOver(struct gameState *state) {
  int i;
  int j;
	
  //if stack of Province cards is empty, the game ends
  if (state->supplyCount[province] == 0)
    {
      return 1;
    }

  //if three supply pile are at 0, the game ends
  j = 0;
  for (i = 0; i <= treasure_map; i++) {
    if (state->supplyCount[i] == 0) {
      j++;
    }
  }
  
  // If 4 or more of the supply counts are empty, or if less than
  // 4 players and 3 or more of the supply counts are empty, the
  // game ends
  if ((j >= 4) || (state->numPlayers < 4 && j >= 3)) {
    return 1;
  }

  return 0;
}

int scoreFor (int player, struct gameState *state) {

  int i;
  int score = 0;
  //score from hand
  for (i = 0; i < state->handCount[player]; i++)
    {
      if (state->hand[player][i] == curse) { score = score - 1; };
      if (state->hand[player][i] == estate) { score = score + 1; };
      if (state->hand[player][i] == duchy) { score = score + 3; };
      if (state->hand[player][i] == province) { score = score + 6; };
      if (state->hand[player][i] == great_hall) { score = score + 1; };
      if (state->hand[player][i] == gardens) { score = score + ( fullDeckCount2(player, state) / 10 ); };
    }

  //score from discard
  for (i = 0; i < state->discardCount[player]; i++)
    {
      if (state->discard[player][i] == curse) { score = score - 1; };
      if (state->discard[player][i] == estate) { score = score + 1; };
      if (state->discard[player][i] == duchy) { score = score + 3; };
      if (state->discard[player][i] == province) { score = score + 6; };
      if (state->discard[player][i] == great_hall) { score = score + 1; };
      if (state->discard[player][i] == gardens) { score = score + ( fullDeckCount2(player, state) / 10 ); };
    }

  //score from deck
  for (i = 0; i < state->deckCount[player]; i++)
    {
      if (state->deck[player][i] == curse) { score = score - 1; };
      if (state->deck[player][i] == estate) { score = score + 1; };
      if (state->deck[player][i] == duchy) { score = score + 3; };
      if (state->deck[player][i] == province) { score = score + 6; };
      if (state->deck[player][i] == great_hall) { score = score + 1; };
      if (state->deck[player][i] == gardens) { score = score + ( fullDeckCount2(player, state) / 10 ); };
    }

  return score;
}

int getWinners(int players[MAX_PLAYERS], struct gameState *state) {
  int i;	
  int j;
  int highScore;
  int currentPlayer;

  //get score for each player
  for (i = 0; i < MAX_PLAYERS; i++) {
    //set unused player scores to -9999
    if (i >= state->numPlayers) {
      players[i] = -9999;
    
    } else {
      players[i] = scoreFor (i, state);
    }
  }

  //find highest score
  j = 0;
  for (i = 0; i < MAX_PLAYERS; i++) {
    if (players[i] > players[j]) {
      j = i;
    }
  }
  highScore = players[j];

  //add 1 to players who had less turns
  currentPlayer = whoseTurn(state);
  for (i = 0; i < MAX_PLAYERS; i++) {
    if ( players[i] == highScore && i > currentPlayer ) {
      players[i]++;
    }
  }

  //find new highest score
  j = 0;
  for (i = 0; i < MAX_PLAYERS; i++) {
    if (players[i] > players[j]) {
      j = i;
    }
  }
  highScore = players[j];

  //set winners in array to 1 and rest to 0
  for (i = 0; i < MAX_PLAYERS; i++) {
    if (players[i] == highScore) {
      players[i] = 1;

    } else {
      players[i] = 0;
    }
  }
  return 0;
}

int drawCard(int player, struct gameState *state)
{	int count;
  int deckCounter;
  if (state->deckCount[player] <= 0){//Deck is empty
    
    //Step 1 Shuffle the discard pile back into a deck
    int i;
    //Move discard to deck
    for (i = 0; i < state->discardCount[player];i++){
      state->deck[player][i] = state->discard[player][i];
      state->discard[player][i] = -1;
    }

    state->deckCount[player] = state->discardCount[player];
    state->discardCount[player] = 0;//Reset discard

    //Shufffle the deck
    shuffle(player, state);//Shuffle the deck up and make it so that we can draw
   
    if (DEBUG){//Debug statements
      printf("Deck count now: %d\n", state->deckCount[player]);
    }
    
    state->discardCount[player] = 0;

    //Step 2 Draw Card
    count = state->handCount[player];//Get current player's hand count
    
    if (DEBUG){//Debug statements
      printf("Current hand count: %d\n", count);
    }
    
    deckCounter = state->deckCount[player];//Create a holder for the deck count

    if (deckCounter == 0)
      return -1;

    state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand
    state->deckCount[player]--;
    state->handCount[player]++;//Increment hand count
  }

  else{
    int count = state->handCount[player];//Get current hand count for player
    int deckCounter;
    if (DEBUG){//Debug statements
      printf("Current hand count: %d\n", count);
    }

    deckCounter = state->deckCount[player];//Create holder for the deck count
    state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand
    state->deckCount[player]--;
    state->handCount[player]++;//Increment hand count
  }

  return 0;
}

int getCost(int cardNumber)
{
  switch( cardNumber ) 
    {
    case curse:
      return 0;
    case estate:
      return 2;
    case duchy:
      return 5;
    case province:
      return 8;
    case copper:
      return 0;
    case silver:
      return 3;
    case gold:
      return 6;
    case adventurer:
      return 6;
    case council_room:
      return 5;
    case feast:
      return 4;
    case gardens:
      return 4;
    case mine:
      return 5;
    case remodel:
      return 4;
    case smithy:
      return 4;
    case village:
      return 3;
    case baron:
      return 4;
    case great_hall:
      return 3;
    case minion:
      return 5;
    case steward:
      return 3;
    case tribute:
      return 5;
    case ambassador:
      return 3;
    case cutpurse:
      return 4;
    case embargo: 
      return 2;
    case outpost:
      return 5;
    case salvager:
      return 4;
    case sea_hag:
      return 4;
    case treasure_map:
      return 4;
    }
	
  return -1;
}

int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus)
{
  int i;
  int currentPlayer = whoseTurn(state);

  int temphand[MAX_HAND];// moved above the if statement
  int drawntreasure=0;
  int cardDrawn;
  int z = 0;// this is the counter for the temp hand
	
  //uses switch to select card and perform actions
  switch( card ) 
    {
    case adventurer:
      while(drawntreasure<2){
	if (state->deckCount[currentPlayer] <1){//if the deck is empty we need to shuffle discard and add to deck
	  shuffle(currentPlayer, state);
	}
	drawCard(currentPlayer, state);
	cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]-1];//top card of hand is most recently drawn card.
	if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold)
	  drawntreasure++;
	else{
	  temphand[z]=cardDrawn;
	  state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one).
	  z++;
	}
      }
      while(z-1>=0){
	state->discard[currentPlayer][state->discardCount[currentPlayer]++]=temphand[z-1]; // discard all cards in play that have been drawn
	z=z-1;
      }
      return 0;
			
    case council_room:
      //+4 Cards
      for (i = 0; i < 4; i++)
	{
	  drawCard(currentPlayer, state);
	}
			
      //+1 Buy
      state->numBuys++;
			
      //Each other player draws a card
      for (i = 0; i < state->numPlayers; i++)
	{
	  if ( i != currentPlayer )
	    {
	      drawCard(i, state);
	    }
	}
			
      //put played card in played card pile
      discardCard(handPos, currentPlayer, state, 0);
			
      return 0;
			
    case feast:
      return card_feast(currentPlayer, choice1, state, temphand, handPos);
			
    case gardens:
      return -1;
			
    case mine:
      return card_mine(currentPlayer, choice1, choice2, state, handPos);
			
    case remodel:
      return card_remodel(currentPlayer, choice1, choice2, state, handPos);
		
    case smithy:
      //+3 Cards
      for (i = 0; i < 3; i++)
	{
	  drawCard(currentPlayer, state);
	}
			
      //discard card from hand
      discardCard(handPos, currentPlayer, state, 0);
      return 0;
		
    case village:
      //+1 Card
      drawCard(currentPlayer, state);
			
      //+2 Actions
      state->numActions = state->numActions + 2;
			
      //discard played card from hand
      discardCard(handPos, currentPlayer, state, 0);
      return 0;
		
    case baron:
      return card_baron(currentPlayer, choice1, state);
		
    case great_hall:
      return card_great_hall(currentPlayer, state, handPos);
		
    case minion:
      return card_minion(currentPlayer, choice1, choice2, state, handPos);
		
    case steward:
      return card_steward(currentPlayer, choice1, choice2, choice3, state, handPos);
		
    case tribute:
      return card_tribute(currentPlayer, state, handPos);
		
    case ambassador:
      return card_ambassador(currentPlayer, choice1, choice2, state, handPos);
		
    case cutpurse:
      return card_cutpurse(currentPlayer, state, handPos);
		
    case embargo: 
      return card_embargo(currentPlayer, choice1, state, handPos);
		
    case outpost:
      //set outpost flag
      state->outpostPlayed++;
			
      //discard card
      discardCard(handPos, currentPlayer, state, 0);
      return 0;
		
    case salvager:
      return card_salvager(currentPlayer, choice1, state, handPos);

    case sea_hag:
      return card_sea_hag(currentPlayer, state, handPos);
		
    case treasure_map:
      return card_treasure_map(currentPlayer, state, handPos);
    }
	
  return -1;
}

int discardCard(int handPos, int currentPlayer, struct gameState *state, int trashFlag)
{
	
  //if card is not trashed, added to Played pile 
  if (trashFlag < 1)
    {
      //add card to played pile
      state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos]; 
      state->playedCardCount++;
    }
	
  //set played card to -1
  state->hand[currentPlayer][handPos] = -1;
	
  //remove card from player's hand
  if ( handPos == (state->handCount[currentPlayer] - 1) ) 	//last card in hand array is played
    {
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }
  else if ( state->handCount[currentPlayer] == 1 ) //only one card in hand
    {
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }
  else 	
    {
      //replace discarded card with last card in hand
      state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)];
      //set last card to -1
      state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1;
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }
	
  return 0;
}

int gainCard(int supplyPos, struct gameState *state, int toFlag, int player)
{
  //Note: supplyPos is enum of choosen card
	
  //check if supply pile is empty (0) or card is not used in game (-1)
  if ( supplyCount(supplyPos, state) < 1 )
    {
      return -1;
    }
	
  //added card for [whoseTurn] current player:
  // toFlag = 0 : add to discard
  // toFlag = 1 : add to deck
  // toFlag = 2 : add to hand

  if (toFlag == 1)
    {
      state->deck[ player ][ state->deckCount[player] ] = supplyPos;
      state->deckCount[player]++;
    }
  else if (toFlag == 2)
    {
      state->hand[ player ][ state->handCount[player] ] = supplyPos;
      state->handCount[player]++;
    }
  else
    {
      state->discard[player][ state->discardCount[player] ] = supplyPos;
      state->discardCount[player]++;
    }
	
  //decrease number in supply pile
  state->supplyCount[supplyPos]--;
	 
  return 0;
}

int updateCoins(int player, struct gameState *state, int bonus)
{
  int i;
	
  //reset coin count
  state->coins = 0;

  //add coins for each Treasure card in player's hand
  for (i = 0; i < state->handCount[player]; i++)
    {
      if (state->hand[player][i] == copper)
	{
	  state->coins += 1;
	}
      else if (state->hand[player][i] == silver)
	{
	  state->coins += 2;
	}
      else if (state->hand[player][i] == gold)
	{
	  state->coins += 3;
	}	
    }	

  //add bonus
  state->coins += bonus;

  return 0;
}

int card_cutpurse(int currentPlayer, struct gameState *state, int handPos)
{
  int i;
  int j;
  int k;

  updateCoins(currentPlayer, state, 2);
  for (i = 0; i < state->numPlayers; i++)
  {
    if (i != currentPlayer)
    {
      for (j = 0; j < state->handCount[i]; j++)
      {
        if (state->hand[i][j] == copper)
        {
          discardCard(j, i, state, 0);
          break;
        }
        if (j == state->handCount[i])
        {
          for (k = 0; k < state->handCount[i]; k++)
          {
            if (DEBUG)
              printf("Player %d reveals card number %d\n", i, state->hand[i][k]);
          } 
          break;
        }   
      }    
    }        
  }

  //discard played card from hand
  discardCard(handPos, currentPlayer, state, 0);

  return 0;
}

int card_embargo(int currentPlayer, int choice1, struct gameState *state, int handPos)
{ 
  //+2 Coins
  state->coins = state->coins + 2;
      
  //see if selected pile is in play
  if (state->supplyCount[choice1] == -1) {
    return -1;
  }
      
  //add embargo token to selected supply pile
  state->embargoTokens[choice1]++;

  //trash card
  discardCard(handPos, currentPlayer, state, 1);    
  return 0;
}

int card_baron(int currentPlayer, int choice1, struct gameState *state)
{
  state->numBuys++;
  if (choice1 > 0) {
    int p = 0;
    int card_not_discarded = 1;
    while (card_not_discarded) {
      if (state->hand[currentPlayer][p] == estate) {
        state->coins += 4;

        // Add estate card to discard
        state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p];
        state->discardCount[currentPlayer]++;
        
        // Remove estate card from hand
        for (; p < state->handCount[currentPlayer]; p++) {
          state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1];
        }
        state->hand[currentPlayer][state->handCount[currentPlayer]] = -1;
        state->handCount[currentPlayer]--;

        card_not_discarded = 0;
      
      } else if (p > state->handCount[currentPlayer]) {
        if (DEBUG) {
          printf("No estate cards in your hand, invalid choice\n");
          printf("Must gain an estate if there are any\n");
        }

        if (supplyCount(estate, state) > 0) {
          gainCard(estate, state, 0, currentPlayer);
          state->supplyCount[estate]--;
          if (supplyCount(estate, state) == 0) {
            isGameOver(state);
          }
        }

        card_not_discarded = 0;
      
      } else {
        p++;

      }
    }
  } else {
    if (supplyCount(estate, state) > 0) {
      gainCard(estate, state, 0, currentPlayer);
      state->supplyCount[estate]--;
      if (supplyCount(estate, state) == 0) {
        isGameOver(state);
      }
    }  
  }
  return 0;
}


int card_great_hall(int currentPlayer, struct gameState *state, int handPos)
{
  //+1 Card
  drawCard(currentPlayer, state);

  //+1 Actions
  state->numActions++;

  //discard card from hand
  discardCard(handPos, currentPlayer, state, 0);
  return 0;
}

int card_mine(int currentPlayer, int choice1, int choice2, struct gameState *state, int handPos)
{
  int i;
  int j;

  j = state->hand[currentPlayer][choice1];  //store card we will trash

  if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold)
  {
    return -1;
  }

  if (choice2 > gold || choice2 < copper)
  {
    return -1;
  }

  if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) )
  {
    return -1;
  }

  gainCard(choice2, state, 2, currentPlayer);

  //discard card from hand
  discardCard(handPos, currentPlayer, state, 0);

  //discard trashed card
  for (i = 0; i < state->handCount[currentPlayer]; i++)
  {
    if (state->hand[currentPlayer][i] == j)
    {
      discardCard(i, currentPlayer, state, 0);      
      break;
    }
  }
  return 0;
}

int card_steward(int currentPlayer, int choice1, int choice2, int choice3, struct gameState *state, int handPos)
{
  int i, toss_card2;

  if (choice1 == 1) {
    //+2 cards
    drawCard(currentPlayer, state);
    drawCard(currentPlayer, state);
  
  } else if (choice1 == 2) {
    //+2 coins
    state->coins = state->coins + 2;
  
  } else {
    // Make sure choices are valid 
    // (not above # cards in hand, not handPos, not below 0)
    if ((choice2 >= state->handCount[currentPlayer]) || 
        (choice3 >= state->handCount[currentPlayer]) ||
        (choice2 == handPos) || 
        (choice3 == handPos) ||
        (choice2 < 0) ||
        (choice3 < 0)) {
      return -1;
    }

    // save card choice for 2nd card
    toss_card2 = state->hand[currentPlayer][choice3];

    // trash 1st card in hand
    discardCard(choice2, currentPlayer, state, 1);

    // trash 2nd card in hand
    for (i = 0; i < state->handCount[currentPlayer]; i++) {
      if (state->hand[currentPlayer][i] == toss_card2) {
        discardCard(i, currentPlayer, state, 1);
        break;
      }
    }
  }

  //discard card from hand
  if (choice1 == 0) {
    for (i = 0; i < state->handCount[currentPlayer]; i++) {
      if (state->hand[currentPlayer][i] == steward) {
        discardCard(i, currentPlayer, state, 1);
        break;
      }
    }
  } else {
    discardCard(handPos, currentPlayer, state, 0);
  }

  return 0;
}

int card_remodel(int currentPlayer, int choice1, int choice2, struct gameState *state, int handPos)
{
  int i, j;

  j = state->hand[currentPlayer][choice1];  //store card we will trash

  if ((getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2)) {
    return -1;
  }

  gainCard(choice2, state, 0, currentPlayer);

  //discard card from hand
  discardCard(handPos, currentPlayer, state, 0);

  //discard trashed card
  for (i = 0; i < state->handCount[currentPlayer]; i++) {
    if (state->hand[currentPlayer][i] == j) {
      discardCard(i, currentPlayer, state, 0);      
      break;
    }
  }

  return 0;
}

int card_feast(int currentPlayer, int choice1, struct gameState *state, int temphand[MAX_PLAYERS], int handPos)
{
  int i;
  int x;

  //gain card with cost up to 5
  //Backup hand
  for (i = 0; i <= state->handCount[currentPlayer]; i++) {
    temphand[i] = state->hand[currentPlayer][i];//Backup card
    state->hand[currentPlayer][i] = -1;//Set to nothing
  }
  //Backup hand

  //Update Coins for Buy
  updateCoins(currentPlayer, state, 5);
  x = 1;//Condition to loop on
  while( x == 1) {//Buy one card
    if (supplyCount(choice1, state) <= 0) {
      if (DEBUG)
        printf("None of that card left, sorry!\n");

      if (DEBUG) {
        printf("Cards Left: %d\n", supplyCount(choice1, state));
      }
    } else if (state->coins < getCost(choice1)){
      printf("That card is too expensive!\n");

      if (DEBUG) {
        printf("Coins: %d < %d\n", state->coins, getCost(choice1));
      }
    } else {
      if (DEBUG){
        printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]);
      }

      gainCard(choice1, state, 0, currentPlayer);//Gain the card
      x = 0;//No more buying cards

      if (DEBUG) {
        printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]);
      }
    }
  }     

  //Reset Hand
  for (i = 0; i <= state->handCount[currentPlayer]; i++) {
    state->hand[currentPlayer][i] = temphand[i];
    temphand[i] = -1;
  }
  //Reset Hand

  return 0;
}

int card_minion(int currentPlayer, int choice1, int choice2, struct gameState *state, int handPos)
{
  int i, j;

  //+1 action
  state->numActions++;

  //discard card from hand
  discardCard(handPos, currentPlayer, state, 0);

  if (choice1) {      //+2 coins
    state->coins = state->coins + 2;
    
  } else if (choice2) { //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4
    
    //discard hand
    while(numHandCards(state) > 0) {
      discardCard(0, currentPlayer, state, 0);
    }

    //draw 4
    for (i = 0; i < 4; i++) {
      drawCard(currentPlayer, state);
    }

    //other players discard hand and redraw if hand size > 4
    for (i = 0; i < state->numPlayers; i++) {
      if (i != currentPlayer) {
        if (state->handCount[i] > 4) {
          //discard hand
          while( state->handCount[i] > 0 ) {
            discardCard(0, i, state, 0);
          }

          //draw 4
          for (j = 0; j < 4; j++) {
            drawCard(i, state);
          }
        }
      }
    }
  }
  return 0;
}

int card_salvager(int currentPlayer, int choice1, struct gameState *state, int handPos)
{
  int i;

  //+1 buy
  state->numBuys++;
 
  if (choice1 != handPos) {
    //gain coins equal to trashed card
    state->coins = state->coins + getCost(handCard(choice1, state));
    //trash card
    discardCard(choice1, currentPlayer, state, 1);  
  }
      
  //discard card
  for (i = 0; i < state->handCount[state->whoseTurn]; i++) {
    if (state->hand[state->whoseTurn][i] == salvager) {
      discardCard(i, currentPlayer, state, 0);
      break;
    }
  }

  return 0;  
}

int card_ambassador(int currentPlayer, int choice1, int choice2, struct gameState *state, int handPos)
{
  int i, j, card;

  j = 0;    //used to check if player has enough cards to discard

  //Save card to toss
  card = state->hand[currentPlayer][choice1];

  if (choice2 > 2 || choice2 < 0) {
    return -1;        
  }

  if (choice1 == handPos) {
    return -1;
  }

  for (i = 0; i < state->handCount[currentPlayer]; i++) {
    if (i != handPos && state->hand[state->whoseTurn][i] == card) {
      j++;
    }
  }
  if (j < choice2) {
    return -1;        
  }

  if (DEBUG) 
    printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]);

  //increase supply count for choosen card by amount being discarded
  state->supplyCount[card] += choice2;

  //each other player gains a copy of revealed card
  for (i = 0; i < state->numPlayers; i++) {
    if (i != currentPlayer) {
      gainCard(card, state, 0, i);
    }
  }

  //discard played card from hand
  discardCard(handPos, currentPlayer, state, 0);      

  //trash copies of cards returned to supply
  for (j = 0; j < choice2; j++) {
    for (i = 0; i < state->handCount[currentPlayer]; i++) {
      if (state->hand[currentPlayer][i] == card) {
        discardCard(i, currentPlayer, state, 1);
        break;
      }
    }
  }     

  return 0;
}

int card_tribute(int currentPlayer, struct gameState *state, int handPos)
{
  int i;
  int tributeRevealedCards[2] = {-1, -1};
  int nextPlayer = currentPlayer + 1;
  int cards;

  if (nextPlayer > (state->numPlayers - 1)) {
    nextPlayer = 0;
  }

  // Condition where there is only 1 card in either deck or discard
  // Save discarded card as revealed card
  if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1) {
    if (state->deckCount[nextPlayer] > 0) {
      tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
      state->deckCount[nextPlayer]--;
    
    } else if (state->discardCount[nextPlayer] > 0) {
      tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1];
      state->discardCount[nextPlayer]--;
    
    } else {
      //No Card to Reveal
      if (DEBUG){
        printf("No cards to reveal\n");
      }
    }

  // Condition where there is only 1 card in deck but 1 or more in discard
  } else if (state->deckCount[nextPlayer] == 1 && state->discardCount[nextPlayer] >= 1) {
    
    tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
    state->deck[nextPlayer][state->deckCount[nextPlayer]] = -1;
    state->deckCount[nextPlayer]--;

    cards = state->discardCount[nextPlayer];
    for (i = 0; i < cards; i++) {
      state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck
      state->deckCount[nextPlayer]++;
      state->discard[nextPlayer][i] = -1;
      state->discardCount[nextPlayer]--;
    }

    shuffle(nextPlayer,state);//Shuffle the deck

    tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
    state->deck[nextPlayer][state->deckCount[nextPlayer]] = -1;
    state->deckCount[nextPlayer]--;

  } else {

    // Put discard back into deck if empty
    if (state->deckCount[nextPlayer] == 0) {
      cards = state->discardCount[nextPlayer];
      for (i = 0; i < cards; i++) {
        state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck
        state->deckCount[nextPlayer]++;
        state->discard[nextPlayer][i] = -1;
        state->discardCount[nextPlayer]--;
      }

      shuffle(nextPlayer,state);//Shuffle the deck
    } 

    // Save 2 discarded cards as revealed cards
    tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
    state->deck[nextPlayer][state->deckCount[nextPlayer]] = -1;
    state->deckCount[nextPlayer]--;
    tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
    state->deck[nextPlayer][state->deckCount[nextPlayer]] = -1;
    state->deckCount[nextPlayer]--;
  }    

  // Add tributed card to top of discard
  for (i = 0; i < 2; i++) {
    if (tributeRevealedCards[i] == -1) {
      break;
    }

    state->discard[nextPlayer][state->discardCount[nextPlayer]] = tributeRevealedCards[i];
    state->discardCount[nextPlayer] += 1;
  }

  if (tributeRevealedCards[0] == tributeRevealedCards[1]) {//If we have a duplicate card, just drop one 
    tributeRevealedCards[1] = -1;
  }

  // Loop effect for the 2 revealed cards (THERE's AN OBVIOUS ERROR HERE)
  for (i = 0; i < 2; i ++) {
    if (tributeRevealedCards[i] == -1) {
      break;
    } else if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold) {//Treasure cards
      state->coins += 2;
    
    } else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall) {//Victory Card Found
      drawCard(currentPlayer, state);
      drawCard(currentPlayer, state);
    
    } else {//Action Card
      state->numActions = state->numActions + 2;
    }
  }

  // Discard tribute card
  discardCard(handPos, currentPlayer, state, 0);

  return 0;
}

/**
 * Each other player discards the top card of his deck, 
 * then gains a curse card, putting it on top of his deck.
 * @param  currentPlayer the current player
 * @param  state         the game state
 * @param  handPos       the index of the card being played
 * @return               0 on success
 */
int card_sea_hag(int currentPlayer, struct gameState *state, int handPos)
{
  int i, j, player, cards;
  for (i = 0; i < state->numPlayers; i++) {
    player = (i + state->whoseTurn + 1) % state->numPlayers;

    if (player == state->whoseTurn) {
      continue;
    }

    if (state->deckCount[player] > 0) {
      state->discard[player][state->discardCount[player]] = state->deck[player][state->deckCount[player] - 1];
      state->deck[player][state->deckCount[player] - 1] = -1;
      state->discardCount[player] += 1;
      state->deckCount[player] -= 1;
    } else if (state->discardCount[player] > 0) {
      // Shuffle discard back into deck
      cards = state->discardCount[player];
      for (j = 0; j < cards; j++) {
        state->deck[player][j] = state->discard[player][j];//Move to deck
        state->deckCount[player]++;
          state->discard[player][j] = -1;
          state->discardCount[player]--;
      }
      shuffle(player, state);

      // Discard card
      state->discard[player][state->discardCount[player]] = state->deck[player][state->deckCount[player] - 1];
      state->deck[player][state->deckCount[player] - 1] = -1;
      state->discardCount[player] += 1;
      state->deckCount[player] -= 1;
    }

    if (state->supplyCount[curse] > 0) {
      state->deck[player][state->deckCount[player]] = curse;
      state->deckCount[player] += 1;
      state->supplyCount[curse] -= 1;
    }
  }

  // Discard Sea Hag card
  discardCard(handPos, state->whoseTurn, state, 0);

  return 0;
}

/**
 * Trash this and another copy of treasure map from your hand.
 * If you do trash two Treasure Maps, gain 4 gold cards,
 * putting them on top of your deck
 * @param  currentPlayer the index of the current player
 * @param  state         the game state
 * @param  handPos       the index of the treasure map card
 * @return               0 on success
 */
int card_treasure_map(int currentPlayer, struct gameState *state, int handPos)
{
  int i, j, treasure_count = 0, gain_gold = 4;

  // Count number of treasure cards
  for (i = 0; i < state->handCount[state->whoseTurn]; i++) {
    if (state->hand[state->whoseTurn][i] == treasure_map) {
      treasure_count += 1;
    }
  }

  if (treasure_count >= 2) {
    // Trash 2 treasure cards
    for (i = 0; i < 2; i++) {
      for (j = 0; j < state->handCount[state->whoseTurn]; j++) {
        if (state->hand[state->whoseTurn][i] == treasure_map) {
          discardCard(i, state->whoseTurn, state, 1); // Trash card
          break;
        }
      }
    }

    // Put 4 gold cards on top of current player's deck if possible
    if (gain_gold > state->supplyCount[gold]) {
      gain_gold = state->supplyCount[gold];
    }

    for (i = 0; i < gain_gold; i++) {
      state->deck[state->whoseTurn][state->deckCount[state->whoseTurn]] = gold;
      state->deckCount[state->whoseTurn] += 1;
    }

    state->supplyCount[gold] -= gain_gold;

  } else {
    // Trash card if less than 2 treasure map cards in hand
    discardCard(handPos, state->whoseTurn, state, 1);
  }

  //no second treasure_map found in hand
  return 0;
}

//end of dominion.c

